/*
 * Copyright (c) 2020 pig4cloud Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.pig4cloud.pig.ads.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.api.client.util.Lists;
import com.pig4cloud.pig.ads.runner.SynAdCreativeWorker;
import com.pig4cloud.pig.ads.service.*;
import com.pig4cloud.pig.ads.utils.RedisLock;
import com.pig4cloud.pig.api.dto.AdPlanCreateDto;
import com.pig4cloud.pig.api.dto.AdPlanDto;
import com.pig4cloud.pig.api.dto.TtAdCreativeResponseNew;
import com.pig4cloud.pig.api.entity.AdAssetsTrack;
import com.pig4cloud.pig.api.entity.AdPlan;
import com.pig4cloud.pig.api.entity.AdPlanTemp;
import com.pig4cloud.pig.api.entity.TtAdCreativeTemp;
import com.pig4cloud.pig.api.enums.AdMaterialTypeEnum;
import com.pig4cloud.pig.api.enums.AudiencePackLandTypeEnum;
import com.pig4cloud.pig.api.util.NoRepeatSubmit;
import com.pig4cloud.pig.api.vo.AdConfigReqVo;
import com.pig4cloud.pig.api.vo.TtCreativeErrorResult;
import com.pig4cloud.pig.common.core.util.R;
import com.pig4cloud.pig.common.core.util.RandomUtils;
import com.pig4cloud.pig.common.log.annotation.SysLog;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.task.TaskExecutor;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;


/**
 * 广告批量配置
 * @author hejiale
 *
 */
@Slf4j
@RestController
@RequestMapping("/adConfig")
@Api(value = "adConfig", tags = "广告批量配置模块")
public class AdConfigController {

	@Resource
	private AdPlanTempService adPlanTempService;

	@Resource
	private AdvPlanService advPlanService;

	@Resource
	private TtAdCreativeTempService ttAdCreativeTempService;

	@Resource
	private AdvCreativeService advCreativeService;

	@Resource
	private AdvCreativeServiceDetailService advCreativeServiceDetailService;

	@Resource
	private AdAssetsTrackService adAssetsTrackService;

	@Resource
	private TaskExecutor taskExecutor;

	@Autowired
	private RedisLock redisLock;

	/**
	 * 批量配置保存
	 * 调用头条接口创建广告和创意
	 */
	@NoRepeatSubmit(lockTime = 3000)
	@SysLog("批量配置")
	@RequestMapping("/save")
	public R save(@RequestBody AdConfigReqVo adConfigReqVo) {
		List<Long> adIdList = new ArrayList<>();

		// 1、参数校验
		// 广告主账号ID
		Long advertiserId = adConfigReqVo.getAdvertiserId();
		// 广告组ID
		Long campaignId = adConfigReqVo.getCampaignId();
		// 广告临时表-广告计划ID
		Long adIdLocal = adConfigReqVo.getAdId();
		// 广告计划自定义名称
		String adName = adConfigReqVo.getAdName();

		// 广告创意临时表-广告创意ID
		Long adCreativeIdLocal = adConfigReqVo.getAdCreativeId();
		// 选中的转化(监测链接组)个数-一个计划对应一个转化--可以定义为计划个数
		Integer adNum = adConfigReqVo.getAdNum();
		// 计划与创意配比
		Integer adCreativeNum = adConfigReqVo.getAdCreativeNum();
		if (advertiserId == null || campaignId == null || adIdLocal == null || adCreativeIdLocal == null || StringUtils.isAllBlank(adName)
				|| adNum == null || adNum <= 0) {
			return R.failed("缺失必填参数");
		}

		// 2、根据ID获取临时广告计划
		AdPlanTemp adPlanTemp = adPlanTempService.selectAdPlanTempById(adIdLocal);
		if (adPlanTemp == null) {
			return R.failed("临时表广告计划不存在");
		}

		String trackGroupIds = adPlanTemp.getTrackUrlGroupId();
		if (StringUtils.isBlank(trackGroupIds)
				|| trackGroupIds.split(",").length != adNum) {
			return R.failed("广告计划数量和转化个数不一致");
		}

		// 获取临时广告创意
		TtAdCreativeTemp adCreative = ttAdCreativeTempService.getById(adCreativeIdLocal);
		String creativeMaterialMode = adCreative.getCreativeMaterialMode();
		String creatives = adCreative.getCreatives();

		// 自定义创意配比
		List<List<Object>> adCreativesList = Lists.newArrayList();
		// 程序化创意配比
		List<Map<String, Object>> creativesObjectList = Lists.newArrayList();
		// 广告命名规则逻辑
		List<String> materialNameList = Lists.newArrayList();

		// 自定义创意 当creative_material_mode值为"STATIC_ASSEMBLE"表示程序化创意
		if ("STATIC_ASSEMBLE".equals(creativeMaterialMode)) {
			// 程序化创意配比
			R result = programmedMatching(creatives, adNum, adCreativeNum, materialNameList);
			if (0 != result.getCode()) {
				return result;
			}
			creativesObjectList = (List<Map<String, Object>>) result.getData();
		} else {
			// 自定义创意配比
			R result = customMatching(creatives, adNum, adCreativeNum, materialNameList);
			if (0 != result.getCode()) {
				return result;
			}
			adCreativesList = (List<List<Object>>) result.getData();
		}
		// 广告命名规则逻辑
		List<String> adNameList = this.resetAdName(creatives, advertiserId, campaignId, adNum, adName, creativeMaterialMode, materialNameList);

		try {
			List<Long> trackGroupIdList = new ArrayList<>(Arrays.asList(trackGroupIds.split(","))).stream().map(v -> Long.valueOf(v)).collect(Collectors.toList());
			//获取监测信息
			List<AdAssetsTrack> assetsTrackList = adAssetsTrackService.list(Wrappers.<AdAssetsTrack>lambdaQuery()
					.eq(AdAssetsTrack::getDeleted, 0).in(AdAssetsTrack::getTrackUrlGroupId, trackGroupIdList));
			if (assetsTrackList.size() != trackGroupIdList.size()) {
				return R.failed("转化信息还未同步完成，请稍后再试");
			}
			Map<Long, AdAssetsTrack> assetsTrackMap = assetsTrackList.stream().collect(Collectors.toMap(AdAssetsTrack::getTrackUrlGroupId, Function.identity()));
			List<String> creativeErrorMsgList = new ArrayList<>();
			//循环转化
			for (int i = 0; i < trackGroupIdList.size(); i++) {
				//监测链接组ID
				Long trackGroupId = trackGroupIdList.get(i);
				AdAssetsTrack track = assetsTrackMap.get(trackGroupId);
				// 3、创建广告计划
				AdPlanCreateDto adPlan = new AdPlanCreateDto();
				//临时表数据copy到创建对象
				BeanUtils.copyProperties(adPlanTemp, adPlan);
				adPlan.setAdvertiserId(advertiserId);
				adPlan.setAdName(adNameList.get(i));
				adPlan.setDownloadUrl(track.getDownloadUrl());
				// v2.4.2设置点击监测链接,多个逗号分割
				// 20220408 使用监测链接组不需单独传监测链接
//				adPlan.setActionTrackUrl(track.getActionTrackUrl());
				// 监测链接信息
				adPlan.setTrackGroupId(trackGroupId);
				adPlan.setTrackGroupType("TRACK_URL_GROUP_ID");
				//游戏包名
				adPlan.setDownPackage(track.getPackageName());
				adPlan.setAppType(AudiencePackLandTypeEnum.APP_ANDROID.getType());

				String operation = "enable";
				adPlan.setOperation(operation);
				// v2.4.3 因前端页面的联调转化还没有迁移至创建计划阶段，暂时当选择转化的统计方式为每一次时，计划的深度优化方式必须为每次付费出价(BID_PER_ACTION)
				// 20220408 使用接口实时获取的深度转化方式，下策根据广告账户、资产ID、事件类型-purchase_roi 去查询事件表 statistical_type(统计方式)是否为每一次
				// 20220518 首次付费头条还没有提供枚举值，经过分析不需要传深度优化方式 BID_FIRST_ACTION
				adPlan.setDeepBidType("BID_FIRST_ACTION".equals(adPlan.getDeepBidType()) ? null : adPlan.getDeepBidType());
				advPlanService.createAdvPlan(adPlan);

				// 第三方广告平台计划ID
				Long adId = adPlan.getAdId();
				adIdList.add(adId);

				// 4、分配创意，创建广告创意
				TtAdCreativeTemp adCreativeTmp = new TtAdCreativeTemp();
				BeanUtils.copyProperties(adCreative, adCreativeTmp);
				// 分配创意
				adCreativeTmp.setCreatives(JSON.toJSONString("STATIC_ASSEMBLE".equals(creativeMaterialMode) ? creativesObjectList.get(i) : adCreativesList.get(i)));
				adCreativeTmp.setAdId(adId);
				adCreativeTmp.setAdvertiserId(advertiserId);
				// v2.4.3 前端去除应用名称的输入，改为取对应联调转化的应用名
				// 中文的应用名称
				adCreativeTmp.setAppName(track.getAppName());
				TtAdCreativeResponseNew response = advCreativeService.createAdvCreative(adCreativeTmp);
				if (CollectionUtils.isNotEmpty(response.getErrors())) {
					//创意失败
					List<String> msgList = response.getErrors().stream().filter(Objects::nonNull).distinct().map(TtCreativeErrorResult::getMessage).collect(Collectors.toList());
					creativeErrorMsgList.addAll(msgList);
				}
			}
			//finally 并不是异步的会在return前执行
			try {
				if (CollectionUtils.isNotEmpty(adIdList)) {
					// 拉取第三方广告计划
					advPlanService.getAdPlan(String.valueOf(advertiserId), StringUtils.join(adIdList, ","));
					// 拉取第三方广告创意和创意详情
					adIdList.forEach(adId -> {
						SynAdCreativeWorker synAdCreativeWorker = new SynAdCreativeWorker(advCreativeService, advCreativeServiceDetailService, String.valueOf(advertiserId), adId);
						taskExecutor.execute(synAdCreativeWorker);
					});
				}
			} catch (Exception e) {
				e.printStackTrace();
				log.error("获取广告计划失败", e);
			}
			if (CollectionUtils.isNotEmpty(creativeErrorMsgList)) {
				creativeErrorMsgList = creativeErrorMsgList.stream().distinct().collect(Collectors.toList());
				return R.failed("部分创意创建失败 " + JSON.toJSONString(creativeErrorMsgList));
			}
			return R.ok("广告创建成功！");
		} catch (Throwable e) {
			log.error("批量创建广告失败", e);
			//广告创建成功创意失败的情况
			if (CollectionUtils.isNotEmpty(adIdList)) {
				// 拉取第三方广告计划
				advPlanService.getAdPlan(String.valueOf(advertiserId), StringUtils.join(adIdList, ","));
			}
			return R.failed("广告创建失败：" + (StringUtils.isBlank(e.getMessage()) ? "" : e.getMessage()));
		}
	}

	/**
	 * 自定义创意配比
	 * @param creatives
	 * @param adNum
	 * @param adCreativeNum
	 * @return
	 */
	public R<List<List<Object>>> customMatching(String creatives, int adNum, Integer adCreativeNum, List<String> adNameList){
		List<List<Object>> adCreativesList = Lists.newArrayList();
		JSONArray creativesArray = JSON.parseArray(creatives);
		if (adCreativeNum == null || adCreativeNum <= 0 || creativesArray == null || adCreativeNum > creativesArray.size()) {
			return R.failed("计划与创意配比错误");
		}
		// 创意数量
		int creativeSize = creativesArray.size();
		// 分配创意-避免同一个创意在不同的转化中使用
		// 需要创意数 计划数 * 分配创意数
		int needNum = adNum * adCreativeNum;
		// 创意数 >= 需要创意数
		if (creativeSize >= needNum) {
			// 不重复随机分配
			adCreativesList = RandomUtils.randomEleListNoRepeat(creativesArray.toJavaList(Object.class), adNum, adCreativeNum);
		} else {
			// 完全随机分配
			adCreativesList = RandomUtils.randomEleList(creativesArray.toJavaList(Object.class), adNum, adCreativeNum);
		}

		// 获取视频名称 - 用于创建广告命名规则
		for (List<Object> list : adCreativesList){
			JSONObject object = (JSONObject) list.get(0);
			adNameList.add(object.getString("name"));
		}

		return R.ok(adCreativesList);
	}

	/**
	 * 程序化创意配比
	 * @param creatives
	 * @param adNum
	 * @param adCreativeNum
	 * @return
	 */
	public R<List<Map<String,Object>>> programmedMatching(String creatives, int adNum, Integer adCreativeNum, List<String> adNameList) {
		List<List<Object>> adCreativesList = Lists.newArrayList();
		List<Map<String, Object>> creativesObjectList = Lists.newArrayList();

		JSONObject jsonObject = JSON.parseObject(creatives);
		JSONArray creativesList = JSONArray.parseArray(jsonObject.getString("image_materials"));
		JSONArray arrVideo = JSONArray.parseArray(jsonObject.getString("video_materials"));
		creativesList.addAll(arrVideo);
		// 创意数量  图片数量  +  视频数量
		int creativeSize = creativesList.size();
		if (adCreativeNum == null || adCreativeNum <= 0 || adCreativeNum > creativeSize) {
			return R.failed("计划与创意配比错误");
		}
		// 分配创意-避免同一个创意在不同的转化中使用
		// 需要创意数 计划数 * 分配创意数
		int needNum = adNum * adCreativeNum;


		// 创意数 >= 需要创意数
		if (creativeSize >= needNum) {
			// 不重复随机分配
			adCreativesList = RandomUtils.randomEleListNoRepeat(creativesList, adNum, adCreativeNum);
		} else {
			// 完全随机分配
			adCreativesList = RandomUtils.randomEleList(creativesList, adNum, adCreativeNum);
		}

		for (List<Object> list : adCreativesList) {
			//原始程序化创意JSON格式
			Map<String, Object> map = JSONObject.parseObject(creatives, Map.class);
			JSONArray imgArr = new JSONArray();
			JSONArray videoArr = new JSONArray();

			for (Object obj : list) {
				JSONObject object = JSONObject.parseObject(JSON.toJSONString(obj));
				String imageMode = object.getString("image_mode");
				if ("image".equals(AdMaterialTypeEnum.codeByValue(imageMode))) {
					imgArr.add(object);
				} else if ("video".equals(AdMaterialTypeEnum.codeByValue(imageMode))) {
					videoArr.add(object);
				}
			}

			String adName = "";
			// 获取视频名称 - 用于创建广告命名规则,优先取视频
			if (CollectionUtils.isNotEmpty(videoArr)) {
				JSONObject object = JSONObject.parseObject(JSON.toJSONString(videoArr.getJSONObject(0))).getJSONObject("video_info");
				adName = object.getString("name");
			}
			if (CollectionUtils.isNotEmpty(imgArr) && StringUtils.isBlank(adName)) {
				JSONObject jsonObj = imgArr.getJSONObject(0);
				JSONArray array = jsonObj.getJSONArray("image_info");
				JSONObject obj = array.getJSONObject(0);
				adName = obj.getString("name");
			}
			adNameList.add(adName);

			// 替换原始程序化创意JSON中的图片或视频素材
			map.put("image_materials", imgArr);
			map.put("video_materials", videoArr);
			creativesObjectList.add(map);
		}
		return R.ok(creativesObjectList);
	}

	/**
	 * 广告命名规则逻辑
	 * @param creatives
	 * @param advertiserId
	 * @param campaignId
	 * @param adNum
	 * @param adName
	 * @param names
	 * @return
	 */
	public List<String> resetAdName(String creatives, Long advertiserId, Long campaignId, int adNum, String adName, String creativeMaterialMode, List<String> names) {
		List<String> adNameList = Lists.newArrayList();
		// 所有创意列表
		JSONArray creativesArray = new JSONArray();

		// 程序化创意json
		if ("STATIC_ASSEMBLE".equals(creativeMaterialMode)) {
			JSONObject jsonObject = JSON.parseObject(creatives);
			creativesArray = JSONArray.parseArray(jsonObject.getString("image_materials"));
			JSONArray arrVideo = JSONArray.parseArray(jsonObject.getString("video_materials"));
			creativesArray.addAll(arrVideo);
		}else{
			// 自定义创意json
			creativesArray = JSON.parseArray(creatives);
		}

		int creativeSize = creativesArray.size();
		// 广告命名规则逻辑
		List<String> adNameTmpList = Lists.newArrayList();
		if (creativeSize > 1 && adNum > 1) {
			String[] adNameArr = adName.split("_");
			for (String name : names) {
				// name = 0407_MXSJios_激活-无_111@11_竖版_陈翔
				String adNameTmp = StringUtils.isNotBlank(name) ? adName.replace(adNameArr[3] + "_" + adNameArr[4], name) : adName;
				List<AdPlan> adPlanListTmp = this.getPlanListByName(advertiserId,campaignId,adNameTmp);
				int adCode = adPlanListTmp.size();
				// 重命名名称在集合中已经存在的数量
				// 当创意数不足完全随机时，会出现名称相同
				long adNameCount = adNameTmpList.stream().filter(item -> adNameTmp.equals(item)).count();
				adNameTmpList.add(adNameTmp);

				String nameTmp = adNameTmp + "_" + String.format("%02d", adCode + adNameCount + 1);
				adNameList.add(nameTmp);
			}
		} else {
			// 如果只有一个创意或只有一个计划，使用前段传的默认命名
			List<AdPlan> adPlanListTmp = this.getPlanListByName(advertiserId,campaignId,adName);
			int adCode = adPlanListTmp.size();
			for (int i = 1; i <= adNum; i++) {
				String adNameTmp = adName + "_" + String.format("%02d", adCode + i);
				adNameList.add(adNameTmp);
			}
		}
		return adNameList;
	}

	private List<AdPlan> getPlanListByName(Long advertiserId, Long campaignId, String adName){
		AdPlanDto adPlanDto = new AdPlanDto();
		adPlanDto.setAdvertiserId(String.valueOf(advertiserId));
		adPlanDto.setCampaignId(campaignId);
		adPlanDto.setAdName(adName);
		return advPlanService.getByName(adPlanDto);
	}

	public static void main(String[] args) {
		System.out.println(AdMaterialTypeEnum.codeByValue("CREATIVE_IMAGE_MODE_VIDEO_VERTICAL"));
	}

//	public static void main(String[] args) {
//		List<List<Object>> adCreativesList = Lists.newArrayList();
//		int adNum = 1;
//		// 计划与创意配比
//		Integer adCreativeNum = 2;
//		String creatives = "[{\"component_materials\":[{\"component_id\":\"7064457950991106087\"}],\"video_material\":{\"image_info\":{\"image_id\":\"web.business.image/202203175d0dbe2d16b901a94d118324\"},\"video_info\":{\"name\":\"充六元_竖版\",\"video_id\":\"v02033g10000c8pa07jc77u8orifvjcg\"}},\"derive_poster_cid\":0,\"title_material\":{\"title\":\"快来，武汉小伙伴都爱玩\"},\"name\":\"充六元_竖版\",\"image_mode\":\"CREATIVE_IMAGE_MODE_VIDEO_VERTICAL\",\"sub_title_material\":{\"sub_title\":\"211212\"}},{\"component_materials\":[{\"component_id\":\"7064457950991106087\"}],\"video_material\":{\"image_info\":{\"image_id\":\"web.business.image/202204075d0d3af10d6397be43d1ae73\"},\"video_info\":{\"name\":\"111@11_竖版\",\"video_id\":\"v02033g10000c8rv9qjc77ufd044lqtg\"}},\"derive_poster_cid\":0,\"title_material\":{\"title\":\"快来，武汉小伙伴都爱玩\"},\"name\":\"111@11_竖版\",\"image_mode\":\"CREATIVE_IMAGE_MODE_VIDEO_VERTICAL\",\"sub_title_material\":{\"sub_title\":\"211212\"}}]";
//		System.out.println(creatives);
//		JSONArray creativesArray = JSON.parseArray(creatives);
//		if (adCreativeNum == null || adCreativeNum <= 0 || creativesArray == null || adCreativeNum > creativesArray.size()) {
//			System.out.println("计划与创意配比错误");
//		}
//		// 创意数量
//		int creativeSize = creativesArray.size();
//
//		// 需要创意数 计划数 * 分配创意数
//		int needNum = adNum * adCreativeNum;
//		// 创意数 >= 需要创意数
//		if (creativeSize >= needNum) {
//			// 不重复随机分配
//			adCreativesList = RandomUtils.randomEleListNoRepeat(creativesArray.toJavaList(Object.class), adNum, adCreativeNum);
//		} else {
//			// 完全随机分配
//			adCreativesList = RandomUtils.randomEleList(creativesArray.toJavaList(Object.class), adNum, adCreativeNum);
//		}
//		System.out.println(JSON.toJSONString(adCreativesList));
//	}

//	public static void main(String[] args) {
//		List<String> nameList = Lists.newArrayList();
//		List<List<Object>> adCreativesList = Lists.newArrayList();
//		List<Map<String,Object>> creativesObjectList = Lists.newArrayList();
//		int adNum = 1;
//		// 计划与创意配比
//		Integer adCreativeNum = 2;
//		// 仅视频
////		String creatives = "{\"component_materials\":[{\"component_id\":\"7064457950991106087\"}],\"image_materials\":[],\"sub_title_material\":{\"sub_title\":\"211212\"},\"video_materials\":[{\"image_mode\":\"CREATIVE_IMAGE_MODE_VIDEO_VERTICAL\",\"image_info\":{\"image_id\":\"web.business.image/202111085d0d6f9ff5db1e2a4446aeae\"},\"video_info\":{\"name\":\"小狗和小鸡_竖版\",\"video_id\":\"v03033g10000c649jcbc77u704ghjoag\"}},{\"image_mode\":\"CREATIVE_IMAGE_MODE_VIDEO_VERTICAL\",\"image_info\":{\"image_id\":\"web.business.image/202203215d0df693e12f9c0d4f37b58b\"},\"video_info\":{\"name\":\"111@11_竖版\",\"video_id\":\"v02033g10000c8rv9qjc77ufd044lqtg\"}},{\"image_mode\":\"CREATIVE_IMAGE_MODE_VIDEO_VERTICAL\",\"image_info\":{\"image_id\":\"web.business.image/202203155d0d9d70e637dbee4e56a8d8\"},\"video_info\":{\"name\":\"奇怪合成_竖版\",\"video_id\":\"v03033g10000c8o2j03c77ufobd4pt2g\"}}],\"title_materials\":[{\"title\":\"末日血战，隔壁老王都在玩\"},{\"title\":\"真，末日血战，隔壁老王最爱游戏之一，你值得拥有\"}]}";
//		// 图片和视频
//		String creatives = "{\"component_materials\":[{\"component_id\":\"7064457950991106087\"}],\"image_materials\":[{\"image_mode\":\"CREATIVE_IMAGE_MODE_LARGE\",\"image_info\":[{\"name\":\"横版大图2_大图横图\",\"image_id\":\"337b6000dc99b3a7c956c\"}]}],\"sub_title_material\":{\"sub_title\":\"211212\"},\"video_materials\":[{\"image_mode\":\"CREATIVE_IMAGE_MODE_VIDEO_VERTICAL\",\"image_info\":{\"image_id\":\"web.business.image/202204075d0d3af10d6397be43d1ae73\"},\"video_info\":{\"name\":\"111@11_竖版\",\"video_id\":\"v02033g10000c8rv9qjc77ufd044lqtg\"}},{\"image_mode\":\"CREATIVE_IMAGE_MODE_VIDEO_VERTICAL\",\"image_info\":{\"image_id\":\"web.business.image/202203175d0dbc21d943245d4cf189db\"},\"video_info\":{\"name\":\"充六元_竖版\",\"video_id\":\"v02033g10000c8pa07jc77u8orifvjcg\"}}],\"title_materials\":[{\"word_list\":[{\"word_id\":4},{\"word_id\":1727}],\"title\":\"111{地点}{日期}\"}]}";
//		JSONObject jsonObject = JSON.parseObject(creatives);
//		JSONArray arrImg = JSONArray.parseArray(jsonObject.getString("image_materials"));
//		JSONArray arrVideo = JSONArray.parseArray(jsonObject.getString("video_materials"));
//		// 创意数量  图片数量  +  视频数量
//		int creativeSize = arrImg.size() + arrVideo.size();
//		if (adCreativeNum == null || adCreativeNum <= 0 || adCreativeNum > creativeSize) {
//			System.out.println("计划与创意配比错误");
//		}
//		// 分配创意-避免同一个创意在不同的转化中使用
//		// 需要创意数 计划数 * 分配创意数
//		int needNum = adNum * adCreativeNum;
//		arrImg.addAll(arrVideo);
//		// 创意数 >= 需要创意数
//		if (creativeSize >= needNum) {
//			// 不重复随机分配
//			adCreativesList = RandomUtils.randomEleListNoRepeat(arrImg, adNum, adCreativeNum);
//		} else {
//			// 完全随机分配
//			adCreativesList = RandomUtils.randomEleList(arrImg, adNum, adCreativeNum);
//		}
//		System.out.println(JSON.toJSONString(adCreativesList));
//		for (List<Object> list : adCreativesList){
//			Map<String,Object> map = JSONObject.parseObject(creatives,Map.class);
//			JSONArray imgArr = new JSONArray();
//			JSONArray videoArr = new JSONArray();
//
//			for (Object obj : list){
//				JSONObject object = JSONObject.parseObject(JSON.toJSONString(obj));
//				if ("CREATIVE_IMAGE_MODE_LARGE".equals(object.getString("image_mode"))){
//					imgArr.add(object);
//				}else if("CREATIVE_IMAGE_MODE_VIDEO_VERTICAL".equals(object.getString("image_mode"))){
//					videoArr.add(object);
//				}
//			}
//
//			String name = "";
//			// 获取视频名称 - 用于创建广告命名规则
//			if (CollectionUtils.isNotEmpty(videoArr)){
//				JSONObject object = JSONObject.parseObject(JSON.toJSONString(videoArr.getJSONObject(0))).getJSONObject("video_info");
//				name = object.getString("name");
//			}
//			if (CollectionUtils.isNotEmpty(imgArr) && StringUtils.isBlank(name)){
//				JSONObject jsonObj = imgArr.getJSONObject(0);
//				JSONArray array = jsonObj.getJSONArray("image_info");
//				JSONObject obj = array.getJSONObject(0);
//				name = obj.getString("name");
//			}
//			nameList.add(name);
//
//			map.put("image_materials",imgArr);
//			map.put("video_materials",videoArr);
//			creativesObjectList.add(map);
//		}
//		System.out.println(JSON.toJSONString(creativesObjectList));
//	}
}
